﻿//
// Copyright 2008-2011 by Burt Harris
// Licensed under the Microsoft Public License (Ms-PL)
// See: http://www.codeplex.com/yaml/license
//

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Eventing.Reader;
using System.Security.Principal;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace YaTools.Yaml.UnitTests
{
    /// <summary>
    ///This is a test class for Memento_Mode_EmitterTest and is intended
    ///to contain all Memento_Mode_EmitterTest Unit Tests
    ///</summary>
    [TestClass]
    public class SerializationExperiment
    {
        [ClassInitialize]
        public static void SetupReflection(TestContext tc)
        {
            Type t = typeof (SecurityIdentifier);
            TypeDescriptor.AddAttributes(t, YamlScalarAttribute.Yes);
        }


#if XPERIMENT
        class MyTypeDescriptorProvider : TypeDescriptionProvider
        {
            public MyTypeDescriptorProvider(TypeDescriptionProvider parent)
                : base(parent) { }
            public override ICustomTypeDescriptor  GetTypeDescriptor(Type objectType, object instance)
            {
                return new MyCustomTypeDescriptor( base.GetTypeDescriptor(objectType, instance));
            }
        }

        class MyCustomTypeDescriptor : CustomTypeDescriptor
        {
            public MyCustomTypeDescriptor( ICustomTypeDescriptor parent)
                : base(parent)
            {
            }

            public override PropertyDescriptorCollection GetProperties()
            {
                return new MyPropertyDescriptorCollection(base.GetProperties());
            }

            public override PropertyDescriptorCollection  GetProperties(Attribute[] attributes)
            {
                return new MyPropertyDescriptorCollection(base.GetProperties(attributes));
            }
        }

        class MyPropertyDescriptorCollection : PropertyDescriptorCollection
        {
            PropertyDescriptorCollection _parent;

            public MyPropertyDescriptorCollection(PropertyDescriptorCollection parent)
                : base(null)
            {
                _parent = parent;
            }

            public override PropertyDescriptor Find(string name, bool ignoreCase)
            {
                PropertyDescriptor result = _parent.Find(name, ignoreCase);
                if (name == "IsLocked")
                    result = TypeDescriptor.CreateProperty(result.ComponentType, result,
                        new DefaultValueAttribute(false));
                return result;
            }
        }
#endif

        [TestMethod]
        public void TrySerialization()
        {
            var value = new Hashtable
                            {
                                {"Name", "TrySerialization"},
                                {"Today", DateTime.Today},
                                {"Now", DateTime.Now},
                                {"Zero", 0},
                                {"UtcNow", DateTime.UtcNow},
                                {"List as value", new ArrayList {1, 2, 3}},
                                {"Type", GetType()},
                                {"Funny, key", "Funny, value"},
                                {"[brackets]", "{Braces}"},
                                {new[] {1, 2, 3}, "List as a key"}
                            };

            DebugSerialize(value);
        }

        [TestMethod]
        public void TrySerializeLogs()
        {
            var d = new Dictionary<string, EventLogInformation>();

            using (var session = new EventLogSession())
            {
                foreach (string name in session.GetLogNames())
                {
                    try
                    {
                        d.Add(name, session.GetLogInformation(name, PathType.LogName));
                    }
                    catch (UnauthorizedAccessException)
                    {
                    }
                    catch (EventLogNotFoundException)
                    {
                    }
                }
            }
            DebugSerialize(d);
        }

        private static void DebugSerialize(object value)
        {
            var dumper = new Dump(new Dump.Presenter.Yaml.Explicit());

            try
            {
                dumper.Serialize(Console.Out, value);
            }
            catch (Exception ex)
            {
                //
                // Wrapping it in an AssertFailedException makes the error message easier to see in the Test Results window...
                // rather than saying "Test method bla.bla.bla threw exception:"
                //
                throw new AssertFailedException(ex.Message, ex);
            }
        }
        
        [TestMethod]
        public void TryTagged()
        {
            var value = new TaggedDictionary(Tag.TaggedMap)
                            {
                                {"Name", "TryTagged"},
                                {"Today", DateTime.Today},
                                {
                                    "List as value", new TaggedSequence(Tag.TaggedSeq)
                                                         {1, 2, 3}
                                    },
                                {"Type", new TaggedScalar(Tag.TaggedScalar, "Greetings earthlings")},
                                {"Funny, key", "Funny, value"},
                                {"[brackets]", "{Braces}"},
                            };

            DebugSerialize(value);
        }


        public TestContext TestContext { get; set; }
    }
}